# -*- coding: utf-8 -*-
# Gestión de constantes de módulo.

## vipera, un diseñador de aplicaciones para Python
##     Copyright (C) 2011 Ángel Luis García García
##
##    This program is free software: you can redistribute it and/or modify
##    it under the terms of the GNU General Public License as published by
##    the Free Software Foundation, either version 3 of the License, or
##    (at your option) any later version.
##
##    This program is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##    GNU General Public License for more details.
##
##    You should have received a copy of the GNU General Public License
##    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import wx

from constantes_vista import panel_cte, panel_cte_dicc
from i18n_vipera import t

class dialogo(wx.Dialog):
    '''Clase para diálogo de menús'''
    def __init__(self, parent, opcion = 0, idioma = None):
        '''Constructor de clase'''
        # Definimos parámetros.
        if opcion == 0: titulo = t('Constantes', idioma)
        if opcion == 1: titulo = t('Diccionario de constantes', idioma)
        wx.Dialog.__init__(self, parent, title = titulo,style=wx.DEFAULT_DIALOG_STYLE)
        # Sizer principal.
        sizer = wx.BoxSizer(wx.VERTICAL)
        # Primer elemento.
        box = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(self, -1, t("Clave/Constante", idioma))
        box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.text_clave = wx.TextCtrl(self, -1, "", size=(80,-1))
        self.text_clave.SetFocus()
        box.Add(self.text_clave, 1, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        # Segundo elemento.
        box = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(self, -1, t("Valor", idioma))
        box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.text_valor = wx.TextCtrl(self, -1, "", size=(80,-1))
        box.Add(self.text_valor, 1, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        # Línea de separación y botones.
        line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
        sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5)
        btnsizer = wx.StdDialogButtonSizer()
        btn = wx.Button(self, wx.ID_OK)
        btn.SetDefault()
        btnsizer.AddButton(btn)
        btn = wx.Button(self, wx.ID_CANCEL)
        btnsizer.AddButton(btn)
        btnsizer.Realize()
        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        self.SetSizer(sizer)
        sizer.Fit(self)

class panel_cte_dicc_p(panel_cte_dicc):
    '''Panel de diccionarios de constantes de módulo'''
    def __init__(self, parent, idioma = None):
        '''Constructor de clase'''        
        panel_cte_dicc.__init__(self, parent)
        self.m_lista_cte.InsertColumn(0,t(u"dict = {'clave':'valor'}", idioma))
        self.m_lista_cte.SetColumnWidth(0, 500)
        
class panel_cte_p(panel_cte):
    '''Panel de constantes de módulo'''
    def __init__(self, parent, idioma = None):
        '''Constructor de clase'''        
        panel_cte.__init__(self, parent)
        # Idioma.
        self.l = idioma
        # Cambiamos idioma en widgets generados por wxFB.
        self.m_notebook_cte.SetPageText(0, t(u'Constantes', self.l))
        self.m_notebook_cte.SetPageText(1, t(u'Diccionarios de constantes', self.l))
        self.m_crear.SetLabel(t(u'Crear', self.l))
        self.m_renombrar.SetLabel(t(u'Renombrar', self.l))
        # Creamos columnas.
        self.__conf_lista_cte(self.m_lista_cte, t(u"constante = 'valor'", self.l))
        # Binding.
        self.m_panel_const.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)

    def cargar_datos(self, dict_constantes):
        '''Cargamos constantes en widgets'''
        lista_cte = dict_constantes['lista_cte']
        lista_cte_dicc = dict_constantes['lista_cte_dicc']
        for j in lista_cte: 
            n_cte = self.m_lista_cte.GetItemCount()
            self.m_lista_cte.InsertStringItem(n_cte, j)
        for j in lista_cte_dicc:
            # Creamos hoja.
            page_o = panel_cte_dicc_p(self.m_aui_nb_dicc_cte, idioma = self.l)
            page_o.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
            # Nombre de diccionario de constante.
            nombre = j[0]
            # Añadimos hoja.
            self.m_aui_nb_dicc_cte.AddPage(page_o, nombre)
            # Y a la hoja le añadimos los campos.
            campos_cte = j[1]
            for k in campos_cte:
                n = page_o.m_lista_cte.GetItemCount()
                page_o.m_lista_cte.InsertStringItem(n, k)
        
    def salvar_datos(self):
        '''Método que recorre las constantes y las devuelve en un diccionario'''
        # Tratamos constantes.
        lista_cte = list()
        n_cte = self.m_lista_cte.GetItemCount()
        for i in range(n_cte):
            j = self.m_lista_cte.GetItem(i).GetText()
            lista_cte.append(j)
        # Tratamos diccionarios de constantes.
        panel_o = self.m_aui_nb_dicc_cte
        nhojas = panel_o.GetPageCount()
        lista_cte_dicc = list()
        for i in range(nhojas):
            # Nombre del diccionario.
            diccionario = panel_o.GetPageText(i)
            # Hoja actual.
            hoja_bis = panel_o.GetPage(i)
            # Recogemos los campos del diccionario.
            lista_campos = list()
            n_dicc = hoja_bis.m_lista_cte.GetItemCount()
            for i in range(n_dicc):
                j = hoja_bis.m_lista_cte.GetItem(i).GetText()
                lista_campos.append(j)
            lista_cte_dicc.append((diccionario, lista_campos))
        # Creamos diccionario de constantes.
        constantes = {'lista_cte' : lista_cte,
                      'lista_cte_dicc' : lista_cte_dicc}
        # Devolvemos diccionario.
        return constantes
    
    def limpiar_widget(self):
        '''Limpiar widgets'''
        self.m_lista_cte.DeleteAllItems()
        n_hojas = self.m_aui_nb_dicc_cte.GetPageCount() 
        for i in range(n_hojas): self.m_aui_nb_dicc_cte.DeletePage(0)

    def OnPageClosed( self, event ):
        '''Event handler para eliminar una hoja'''
        i = wx.MessageBox(t(u"¿Eliminar?", self.l), t(u"Atención", self.l),wx.YES_NO)
        if i != wx.YES: 
            event.Veto() 
         
    def __conf_lista_cte(self, lista, texto):
        '''Configuración de panel de constantes'''
        lista.InsertColumn(0, texto)
        lista.SetColumnWidth(0, 500)
        
    def OnContextMenu(self, event):
        '''Menú contextual'''
        # Crear elemento.
        self.id_crear = wx.NewId()
        self.Bind(wx.EVT_MENU, self.OnCrearCte, id=self.id_crear)
        # Modificar elemento.
        self.id_modificar = wx.NewId()
        self.Bind(wx.EVT_MENU, self.OnModificarCte, id=self.id_modificar)
        # Eliminar elemento.
        self.id_eliminar = wx.NewId()
        self.Bind(wx.EVT_MENU, self.OnEliminarCte, id=self.id_eliminar)
        # Subir un elemento en lo más alto.
        self.id_subir = wx.NewId()
        self.Bind(wx.EVT_MENU, self.OnSubirCte, id=self.id_subir)
        # Bajar un elemento en lo más bajo.
        self.id_bajar = wx.NewId()
        self.Bind(wx.EVT_MENU, self.OnBajarCte, id=self.id_bajar)
        # Creamos un menú.
        menu = wx.Menu()
        # Elementos del menú.
        item_crear = wx.MenuItem(menu, self.id_crear,t("Crear", self.l))
        item_modificar = wx.MenuItem(menu, self.id_modificar,t("Modificar", self.l))
        item_eliminar = wx.MenuItem(menu, self.id_eliminar,t("Eliminar", self.l))
        item_subir = wx.MenuItem(menu, self.id_subir, t("Subir", self.l))
        item_bajar = wx.MenuItem(menu, self.id_bajar, t("Bajar", self.l))
        # Añadimos elementos al menú.
        menu.AppendItem(item_crear)
        menu.AppendItem(item_modificar)
        menu.AppendItem(item_eliminar)
        menu.AppendSeparator()
        menu.AppendItem(item_subir)
        menu.AppendItem(item_bajar)
        # Mostramos el PopMenu.
        self.PopupMenu(menu)
        # Cuando se quita el PopMenu se tiene que limpiar memoria.
        menu.Destroy()
 
    def __pedir_datos(self, opcion = 0):
        '''Pedir datos mediante un wx.TextEntryDialog.'''
        if opcion == 0: cadena = t(u'Nombre del nuevo diccionario: ', self.l)
        if opcion == 1: cadena = t(u'Modificar nombre de diccionario: ', self.l)
        dialogo = wx.TextEntryDialog(self, cadena, t('Constantes', self.l))
        dialogo.Show()
        if dialogo.ShowModal() == wx.ID_OK:
            ret = dialogo.GetValue()
        else:
            # Botón cancelar. Nada que devolver.
            ret = None
        # Limpiamos memoria y nos vamos.
        dialogo.Destroy()
        return ret
 
    def __datos_ctes(self, a, opcion = 0, elem_a_modif = None):
        '''Recuperación e inserción de datos en panel de constantes
        y diccionario de constantes.'''
        # Clave/Valor.
        t1 = a.text_clave.GetValue().strip()
        t2 = a.text_valor.GetValue().strip()
        if len(t1) == 0 or len(t2) == 0: return
        # Formamos cadena.
        cadena1 = '%s = %s' % (t1, t2)        
        cadena2 = '%s : %s' % (t1, t2)        
        if self.m_notebook_cte.GetSelection() == 0:
            # Lo incluimos en el control de lista.
            if opcion == 0:
                n = self.m_lista_cte.GetItemCount()
                self.m_lista_cte.InsertStringItem(n,cadena1)
            if opcion == 1:
                self.m_lista_cte.SetStringItem(elem_a_modif, 0, cadena1)
        if self.m_notebook_cte.GetSelection() == 1:
            # Obtenemos número de hoja actual.
            hoja_actual = self.m_aui_nb_dicc_cte.GetSelection()
            # Obtenemos panel de la hoja actual.
            panel = self.m_aui_nb_dicc_cte.GetPage(hoja_actual)
            if opcion == 0:
                n = panel.m_lista_cte.GetItemCount()
                panel.m_lista_cte.InsertStringItem(n,cadena2)
            if opcion == 1:
                panel.m_lista_cte.SetStringItem(elem_a_modif, 0, cadena2)

    def __mover_item(self):
        '''Movimiento de elementos'''
        if self.m_notebook_cte.GetSelection() == 0: 
            aux = self.m_lista_cte
        if self.m_notebook_cte.GetSelection() == 1: 
            # Obtenemos número de hoja actual.
            hoja_actual = self.m_aui_nb_dicc_cte.GetSelection()
            # Obtenemos panel de la hoja actual.
            panel = self.m_aui_nb_dicc_cte.GetPage(hoja_actual)
            # Y la lista.
            aux = panel.m_lista_cte                       
        if aux.GetSelectedItemCount() > 1:
            wx.MessageBox(t(u"Seleccione solo un elemento a desplazar", self.l), t(u"Atención", self.l), wx.OK)
            return None, None
        # Obtenemos el elemento seleccionado.
        item_sel = aux.GetFirstSelected()
        if item_sel == -1: 
            return None, None
        else: 
            # Guardamos el valor.
            cadena = aux.GetItemText(item_sel)
            # Eliminamos el valor.
            aux.DeleteItem(item_sel)
            # Devolvemos el contenido del elemento.
            return cadena, aux

    def OnSubirCte(self, event):
        '''Subir constante'''
        # Obtenemos el elemento seleccionado.
        cadena, aux = self.__mover_item()
        if cadena is None: return
        # Insertamos el elemento el primero.
        aux.InsertStringItem(0,cadena)
        
    def OnBajarCte(self, event):
        '''Bajar constante'''
        # Obtenemos el elemento seleccionado.
        cadena, aux = self.__mover_item()
        if cadena is None: return
        # Insertamos el elemento el último.
        n = aux.GetItemCount()    
        aux.InsertStringItem(n,cadena)

    def OnCrearCte(self, event):
        '''Crear constante'''
        if self.m_notebook_cte.GetSelection() == 0: 
            a = dialogo(self, idioma = self.l)
        if self.m_notebook_cte.GetSelection() == 1: 
            a = dialogo(self, 1, idioma = self.l)
        a.Show()
        if a.ShowModal() == wx.ID_OK: 
            self.__datos_ctes(a)
        # Limpiamos memoria y nos vamos.
        a.Destroy()

    def OnModificarCte(self, event):
        '''Modificar constante'''
        if self.m_notebook_cte.GetSelection() == 0: 
            aux = self.m_lista_cte
            # Creamos el diálogo.            
            a = dialogo(self, idioma = self.l)
        if self.m_notebook_cte.GetSelection() == 1: 
            # Obtenemos número de hoja actual.
            hoja_actual = self.m_aui_nb_dicc_cte.GetSelection()
            # Obtenemos panel de la hoja actual.
            panel = self.m_aui_nb_dicc_cte.GetPage(hoja_actual)
            # Y la lista.
            aux = panel.m_lista_cte
            # Creamos el diálogo.
            a = dialogo(self, 1, idioma = self.l)
        if aux.GetSelectedItemCount() > 1:
            wx.MessageBox(t(u"Seleccione solo un elemento a modificar", self.l), t(u"Atención", self.l),wx.OK)
            a.Destroy()
            return
        # Obtenemos el elemento seleccionado. Si no hay nada seleccionado, nos vamos.
        item_sel = aux.GetFirstSelected()
        if item_sel == -1: 
            a.Destroy()
            return
        # Mostramos el diálogo.
        a.Show()
        if a.ShowModal() == wx.ID_OK: 
            self.__datos_ctes(a, 1, item_sel)
        # Limpiamos memoria y nos vamos.
        a.Destroy()
        
    def OnEliminarCte(self, event):
        '''Eliminar constante'''
        if self.m_notebook_cte.GetSelection() == 0: 
            aux = self.m_lista_cte
        if self.m_notebook_cte.GetSelection() == 1: 
            # Obtenemos número de hoja actual.
            hoja_actual = self.m_aui_nb_dicc_cte.GetSelection()
            # Obtenemos panel de la hoja actual.
            panel = self.m_aui_nb_dicc_cte.GetPage(hoja_actual)
            # Y la lista.
            aux = panel.m_lista_cte
        while True:
            x = aux.GetFirstSelected()
            aux.DeleteItem(x)
            if x == -1: break
    
    def OnCrear(self, event):
        '''Manejador de eventos para crear diccionario'''
        # Pedimos nombre del módulo.
        i = self.__pedir_datos()
        if i is None: return
        if len(str(i).strip()) == 0: return
        # Creamos la página del módulo.
        page = panel_cte_dicc_p(self.m_aui_nb_dicc_cte, idioma = self.l)
        # Hacemos binding para que funcione el menú contextual.
        page.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
        # Configuramos control de lista de constantes.
        # self.__conf_lista_cte(page.m_lista_cte, u"dict = {'clave':'valor'}")
        # Añadimos la página.
        self.m_aui_nb_dicc_cte.AddPage(page, i.strip())

    def OnRenombrar(self, event):
        '''Manejador de eventos para renombrar un diccionario'''
        # Obtenemos la hoja actual.
        hoja_actual = self.m_aui_nb_dicc_cte.GetSelection()
        # Si no hay hojas, nos vamos.
        if hoja_actual == -1: return
        # Pedimos nombre de función.
        i = self.__pedir_datos(1)
        if i is None: return
        if len(str(i).strip()) == 0: return
        # Cambiamos nombre en la pestaña.
        self.m_aui_nb_dicc_cte.SetPageText(hoja_actual,i)
